/*
 * @Author: your name
 * @Date: 2022-01-25 10:49:52
 * @LastEditTime: 2022-03-15 11:33:58
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: /go-utils/utils/shells.go
 */

package utils

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"runtime/debug"
	"strings"
	"sync"
)

var (
	contentArray []string
)

/**
 * @description: 确认指令
 * @param {string} s
 * @return {*}
 */
func AskForConfirmation(s string) bool {
	reader := bufio.NewReader(os.Stdin)

	for {
		fmt.Printf("%s [y/n]: ", s)

		response, err := reader.ReadString('\n')
		if err != nil {
			log.Fatal(err)
		}

		response = strings.ToLower(strings.TrimSpace(response))

		if response == "y" || response == "yes" {
			return true
		} else if response == "n" || response == "no" {
			return false
		}
	}
}

/**
 * @description: 执行命令
 * @param {string} commandName
 * @param {...string} arg
 * @return {*}
 */
func ExecCommand(commandName string, arg ...string) ([]string, error) {
	contentArray := contentArray[0:0]
	cmd := exec.Command(commandName, arg...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	cmd.Start()

	reader := bufio.NewReader(stdout)
	for {
		line, err2 := reader.ReadString('\n')
		line = strings.ReplaceAll(line, "\r\n", "\n")
		line = strings.ReplaceAll(line, "\n", "")
		if err2 != nil || io.EOF == err2 {
			break
		}
		contentArray = append(contentArray, strings.Trim(line, " "))
	}
	cmd.Wait()
	return contentArray, nil
}

// RunCommand run shell
func RunCommand(out chan string, name string, arg ...string) error {
	cmd := exec.Command(name, arg...)
	stdout, _ := cmd.StdoutPipe()
	stderr, _ := cmd.StderrPipe()
	if err := cmd.Start(); err != nil {
		return err
	}
	wg := sync.WaitGroup{}
	defer wg.Wait()
	wg.Add(2)
	go readLog(&wg, out, stdout)
	go readLog(&wg, out, stderr)
	if err := cmd.Wait(); err != nil {
		return err
	}
	return nil
}

func readLog(wg *sync.WaitGroup, out chan string, reader io.ReadCloser) {
	defer func() {
		if r := recover(); r != nil {
			log.Println(r, string(debug.Stack()))
		}
	}()
	defer wg.Done()
	r := bufio.NewReader(reader)
	for {
		line, _, err := r.ReadLine()
		if err == io.EOF || err != nil {
			return
		}
		out <- string(line)
	}
}
